<template>
  <view class="form-item" :class="{ column }">
    <span class="label">{{ label }}</span>
    <slot :value="modelValue">
      <view class="input-box" :class="{ 'validate-error': isUseValidate && !isValidateSuccess }" @click="clickInput">
        <slot name="input-left"></slot>
        <input
          class="input"
          v-model="value"
          @blur="validate"
          :placeholder="placeholder"
          :disabled="disabled"
          :password="password"
        />
        <slot name="input-right"></slot>
      </view>
    </slot>
  </view>
</template>

<script setup lang="ts">
import { ref, watch, inject, type Ref } from 'vue'

const props = defineProps({
  modelValue: {
    type: null,
    require: true
  },
  label: {
    type: String,
    default: '未定义的标题'
  },
  placeholder: {
    type: String,
    default: ''
  },
  column: {
    type: Boolean,
    default: false
  },
  disabled: {
    type: Boolean,
    default: false
  },
  password: {
    type: Boolean,
    default: false
  },
  rule: {
    type: Object
  },
  prop: {
    type: String,
    default: '__undefined__'
  }
})
const emits = defineEmits<{
  (e: 'update:modelValue', newValue: String | Number): void
  (e: 'click-input'): void
}>()
const value = ref('')
// 内部->外部
watch(
  () => value.value,
  (newValue) => emits('update:modelValue', newValue),
  { immediate: true }
)
// 外部->内部
watch(
  () => props.modelValue,
  (newVal) => (value.value = newVal)
)
function clickInput() {
  emits('click-input')
}
// form-item校验
const isValidateSuccess = ref(true)
const isUseValidate = ref(false)
function validate(): boolean {
  if (props.rule == null || !isUseValidate.value) return true

  return (isValidateSuccess.value = props.rule.test(props.modelValue))
}
// 加入到form校验列表
const formItemStateList = inject<Array<{ prop: string; validate: () => boolean }>>('_validates')
const currentFormItemState = {
  prop: props.prop,
  validate: () => {
    isUseValidate.value = true
    return validate()
  }
}
if (formItemStateList != null) formItemStateList.push(currentFormItemState)
</script>

<style scoped lang="scss">
.column {
  flex-direction: column;
  align-items: flex-start !important;
}

.form-item {
  $form-item-height: 60px;

  display: flex;
  align-items: center;
  min-height: $form-item-height;

  .label {
    padding-right: 50rpx;
    text-wrap: nowrap;
  }

  .validate-error {
    border: 1px solid rgb(255 92 92);
  }

  .input-box {
    $form-item-input: $form-item-height * 0.7;

    position: relative;
    display: flex;
    align-items: center;
    padding: 0 20rpx;
    height: $form-item-input;
    font-size: 26rpx;
    border-radius: $form-item-input * 0.1;
    background-color: #f7f7f7;
    box-sizing: border-box;
    flex-grow: 1;

    .input {
      flex-grow: 1;
      width: 0;
    }
  }
}
</style>
